package com.hj.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.hj.config.FastDFSConfig;

/**
 * @author dehui dou
 * @date 2020/10/3 19:26
 * @description FastDFS文件上传下载工具类
 */
@Component
public class FastDFSClient {

    private static StorageClient1 storageClient1 = null;

    @Autowired
    private FastDFSConfig fastDFSConfig;

    /**
     * @author dehui dou
     * @description 初始化FastDFS Client，api方式
     */
    public void init() {
        try {
            // 连接超时的时限，单位为毫秒
            ClientGlobal.setG_connect_timeout(fastDFSConfig.getConnectTimeout());
            // 网络超时的时限，单位为毫秒
            ClientGlobal.setG_network_timeout(fastDFSConfig.getNetworkTimeout());
            ClientGlobal.setG_anti_steal_token(fastDFSConfig.getCheckToken());
            // 字符集
            ClientGlobal.setG_charset(fastDFSConfig.getCharset());
            ClientGlobal.setG_secret_key(fastDFSConfig.getSecretKey());
            // HTTP访问服务的端口号
            ClientGlobal.setG_tracker_http_port(fastDFSConfig.getTrackerHttpPort());
            // Tracker服务器列表
            String[] szTrackerServers = fastDFSConfig.getTrackerServer();
            InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length];
            for (int i = 0; i < szTrackerServers.length; i++) {
                String[] parts = szTrackerServers[i].split("\\:", 2);
                if (parts.length != 2) {
                    throw new MyException(
                        "the value of item \"tracker_server\" is invalid, the correct format is host:port");
                }
                tracker_servers[i] = new InetSocketAddress(parts[0].trim(), Integer.parseInt(parts[1].trim()));
            }
            ClientGlobal.setG_tracker_group(new TrackerGroup(tracker_servers));

            TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
            TrackerServer trackerServer = trackerClient.getConnection();
            if (trackerServer == null) {
                throw new IllegalStateException("getConnection return null");
            }

            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            if (storageServer == null) {
                throw new IllegalStateException("getStoreStorage return null");
            }

            storageClient1 = new StorageClient1(trackerServer, storageServer);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @author dehui dou
     * @description 文件上传
     * @param buff
     *            文件对象
     * @param fileExtName
     *            文件名
     * @return java.lang.String
     */
    public static String uploadFile(byte[] buff, String fileExtName) throws Exception {
        return uploadFile(buff, fileExtName, null);
    }

    /**
     * @author dehui dou
     * @description 文件上传
     * @param buff
     *            文件对象
     * @param fileExtName
     *            文件名
     * @param metaList
     *            文件元数据
     * @return java.lang.String
     */
    public static String uploadFile(byte[] buff, String fileExtName, Map<String, String> metaList) throws Exception {
        NameValuePair[] nameValuePairs = null;
        if (metaList != null) {
            nameValuePairs = new NameValuePair[metaList.size()];
            int index = 0;
            for (Iterator<Map.Entry<String, String>> iterator = metaList.entrySet().iterator(); iterator.hasNext();) {
                Map.Entry<String, String> entry = iterator.next();
                String name = entry.getKey();
                String value = entry.getValue();
                nameValuePairs[index++] = new NameValuePair(name, value);
            }
        }
        return storageClient1.upload_file1(buff, fileExtName, nameValuePairs);
    }

    /**
     * @author dehui dou
     * @description 获取文件元数据信息
     * @param fileId
     * @return java.util.Map<java.lang.String,java.lang.String>
     */
    public static Map<String, String> getFileMetadata(String fileId) {
        try {
            NameValuePair[] metaList = storageClient1.get_metadata1(fileId);
            if (metaList != null) {
                HashMap<String, String> map = new HashMap<String, String>();
                for (NameValuePair metaItem : metaList) {
                    map.put(metaItem.getName(), metaItem.getValue());
                }
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @author dehui dou
     * @description 文件删除
     * @param fileId
     * @return int 删除失败返回-1，否则返回0
     */
    public static int deleteFile(String fileId) {
        try {
            return storageClient1.delete_file1(fileId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * @author dehui dou
     * @description 文件下载,返回字节数据
     * @param fileId
     * @return byte[] 字节数据
     */
    public static byte[] downloadFile(String fileId) throws IOException, MyException {
        return storageClient1.download_file1(fileId);
    }

    /**
     * @author dehui dou
     * @description 文件下载本地
     * @param fileId
     *            文件ID（上传文件成功后返回的ID）
     * @param outFile
     *            文件下载保存位置
     * @return int
     */

    public static int downloadFile(String fileId, File outFile) {
        FileOutputStream fos = null;
        try {
            byte[] content = storageClient1.download_file1(fileId);
            fos = new FileOutputStream(outFile);
            fos.write(content);
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return -1;
    }
}